﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using PPClasses;

namespace PortalPlan.Solvers
{
    internal class BruteForcer : Solver
    {
        private static Int64 Max;
        private static object NumLock = new object();
        private static Int64 Num;

        public override bool CanThread
        {
            get { return true; }
        }


    private static Int64 NextNum()
        {
            lock (NumLock)
            {
                Int64 r = Num;
                if (Num < Max)
                    Num++;
                PercentDone = (100.0 * Num / Max);
                return r;
            }
        }

        private IEnumerable NextCombo()
        {
            System.Diagnostics.Debug.Assert(PairChoices.Count < 63);

            while (true)
            {
                Int64 num = NextNum();
                if (num == Max)
                    break;
                if (Stop)
                    break;

                List<Pair> res = new List<Pair>();
                bool ok = BuildPairs(num, res);
                if (ok)
                    yield return res;
            }
            CompletelyDone = true;
        }

        public BruteForcer(List<Portal> points) :
            base(points)
        {
            if (PairChoices.Count > 63)
            {
                MessageBox.Show("Too many possible links for this solver", "Brute Force", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
                CompletelyDone = true;
                Max = 0;
                return;
            }
            Num = 0;
            Max = 1L << (PairChoices.Count);
        }

        public override void GoGoGo()
        {
            if (PairChoices.Count > 63)
                return;

            foreach (List<Pair> z in NextCombo())
            {
                EvaluateSolution(z);
                if (Stop)
                    break;
            }

            CompletelyDone = true;
        }

        public override String StatusText()
        {
            return "BruteForce: " + Num+"/"+Max+".  " + base.StatusText();
        }

        private bool BuildPairs(Int64 code, List<Pair> res)
        {
            foreach (Pair p in MustLink)
                res.Add(p);

            for (int i = 0; i < PairChoices.Count; i++)
            {
                if ((code & (1 << i)) != 0)
                {
                    Pair p = PairChoices[i];
                    if (CanAddPair(p, res))
                        res.Add(p);
                    else
                        return false;
                }
            }
            return true;
        }

      


    }
}
